package com.xialinrui.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xialinrui.dto.TodoCompletedDto;
import com.xialinrui.entity.*;
import com.xialinrui.service.*;
import com.xialinrui.utils.TodoUtils;
import com.xialinrui.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.sql.Date;
import java.util.*;

/**
 * @author xialinrui
 */
@RestController
@Slf4j
@RequestMapping("/todo")
public class TodoController {
    @Resource
    private TodoService todoService;
    @Resource
    private AcquirementService acquirementService;
    @Resource
    private UserService userService;
    @Resource
    private TodoCategoryService todoCategoryService;
    @Resource
    private IncomeService incomeService;

    /**
     * 添加任务
     *
     * @param todoVo
     * @return
     */
    @PostMapping("/add")
    public ResponseResult<Map<String, Long>> add(@RequestBody TodoVo todoVo) {
        Map<String, Long> resMap = new HashMap<>(1);
        Long id = todoService.saveWithName(todoVo);
        resMap.put("id", id);
        return new ResponseResult<>(200, "添加成功", resMap);
    }

    /**
     * 删除任务（或任务文件夹）
     *
     * @param areaId
     * @return
     */
    @DeleteMapping("/delete")
    public ResponseResult delete(@RequestParam Long areaId) {
        QueryWrapper<Todo> todoQueryWrapper = new QueryWrapper<>();
        todoQueryWrapper.eq("area_id", areaId);
        Todo todo = todoService.getOne(todoQueryWrapper);
        return todoService.deleteTodo(todo);


    }

    /**
     * 修改任务完成状态为已完成
     * 返回今日总钱数和总爱心数
     *
     * @param completedVo
     * @return
     */
    @PutMapping("/completed")
    public ResponseResult<Map<String, Object>> completed(@RequestBody CompletedVo completedVo) {
        //获取todoId
        Long todoId = completedVo.getTodoId();
        //获取事务id
        Long affairId = completedVo.getAffairId();

        QueryWrapper<Todo> todoQueryWrapper = new QueryWrapper<>();
        todoQueryWrapper.eq("id", todoId);
        Todo todo = todoService.getOne(todoQueryWrapper);

        //在事务-任务表中进行更改
        todoService.changeComplete(todoId, affairId);
        //今日总钱数增加
        acquirementService.increaseAcquire(todoId, affairId);
        if (todo.getMoneyNumbers() > 0) {
            //创建一条收入信息
            Income income = new Income(null, todo.getUpdateTime(), 1L, todo.getName(), todo.getMoneyNumbers());
            //新建一条收入信息
            incomeService.addIncome(income);
            //映射收入字段
            todoService.changeComplete(todoId, affairId, income.getId());
        }
        //返回今日一共有多少钱
        Double moneyNumbersToday = acquirementService.getMoneyNumbersTodayByAffairId(affairId);
        Integer loveNumbersToday = acquirementService.getLoveNumbersTodayByAffairId(affairId);
        Map<String, Object> resMap = new HashMap<>(2);
        resMap.put("moneyNumbersToday", moneyNumbersToday);
        resMap.put("loveNumbersToday", loveNumbersToday);
        return new ResponseResult<>(200, "已经设置为已完成", resMap);
    }

    /**
     * 取消已完成
     *
     * @param id 已完成的任务id
     * @return
     */
    @PutMapping("/not/complete")
    public ResponseResult<List<Affair>> notCompleted(@RequestParam Long id) {
        //根据已完成的任务id就能直接定位到 是哪一天完成的
        Long incomeId = todoService.getCompletedTodoIncomeId(id);
        //扣除今日的获得
        acquirementService.decreaseAcquire(id);
        if (incomeId != null && incomeId != 0) {
            //删除一条账单
            ArrayList<Long> ids = new ArrayList<>();
            ids.add(incomeId);
            incomeService.deleteByIds(ids);
        }
        //状态设置成未完成
        todoService.setIncomplete(id);
        List<Affair> resList = todoService.getTodoInsertedList(id);
        return new ResponseResult<>(200, "已经设置为未完成,data为所有被添加过该任务的事务详情", resList);
    }


    @GetMapping("/area/detail/pre")
    public ResponseResult<String[]> areaDetailPre(@RequestParam String areaId) {
        QueryWrapper<Todo> todoQueryWrapper = new QueryWrapper<>();
        todoQueryWrapper.eq("area_id", areaId);
        Todo todo = todoService.getOne(todoQueryWrapper);
        String[] resList = {};
        if (todo == null) {
            return new ResponseResult<>(200, "查询成功", resList);
        }
        resList = todo.getAreaDetail().split("_");
        return new ResponseResult<>(200, "查询成功", resList);
    }

    /**
     * 重命名任务名或者文件夹名
     *
     * @param todoUpdateVo
     * @return
     */
    @PutMapping("/update")
    public ResponseResult update(@RequestBody TodoUpdateVo todoUpdateVo) {
        Long areaId = todoUpdateVo.getAreaId();
        QueryWrapper<Todo> todoQueryWrapper = new QueryWrapper<>();
        todoQueryWrapper.eq("area_id", areaId);
        Todo todo = todoService.getOne(todoQueryWrapper);
        todo.setTitle(todoUpdateVo.getContent());
        todoService.updateById(todo);
        todoService.adjust(todo);
        return new ResponseResult<>(200, "重命名成功");
    }

    /**
     * 设置任务的金钱获得和爱心获得
     *
     * @param acquireSettingVo
     * @return
     */
    @PutMapping("/set/acquire")
    public ResponseResult setAcquire(@RequestBody AcquireSettingVo acquireSettingVo) {
        UpdateWrapper<Todo> todoUpdateWrapper = new UpdateWrapper<>();
        todoUpdateWrapper.eq("area_id", acquireSettingVo.getAreaId()).set("money_numbers", acquireSettingVo.getMoneyNumbers())
                .set("love_numbers", acquireSettingVo.getLoveNumbers());
        todoService.update(todoUpdateWrapper);
        return new ResponseResult(200, "设置成功");
    }

    @PutMapping("/set/acquire/daily")
    public ResponseResult setAcquireDaily(@RequestParam Long id, @RequestParam Double moneyNumbers, @RequestParam Integer loveNumbers) {
        UpdateWrapper<Todo> todoUpdateWrapper = new UpdateWrapper<>();
        todoUpdateWrapper.eq("id",id).set("money_numbers", moneyNumbers)
                .set("love_numbers", loveNumbers);
        todoService.update(todoUpdateWrapper);
        return new ResponseResult(200, "设置成功");
    }


    /**
     * 根据任务id寻找所有添加过该任务的事务
     *
     * @param id
     * @return
     */
    @GetMapping("/inserted")
    public ResponseResult<List<Affair>> getTodoInserted(@RequestParam Long id) {
        List<Affair> resList = todoService.getTodoInsertedList(id);
        return new ResponseResult<>(200, "查询成功", resList);
    }

    /**
     * 根据分类id查询所有未完成的任务（不包括每日任务）
     *
     * @param id
     * @return
     */
    @GetMapping("/list/category/without/daily/page")
    public ResponseResult<Page<Todo>> getIncompleteTodoListWithOutDailyByCategoryIdByPage(@RequestParam Long id, @RequestParam Integer page, @RequestParam Integer pageSize) {
        Page<Todo> resPage = new Page<>(page, pageSize);
        todoService.getIncompleteTodoListWithOutDailyByCategoryIdNotFolders(resPage, id);
        return new ResponseResult<>(200, "查询成功", resPage);
    }

    @GetMapping("/list/category/without/daily")
    public ResponseResult<List<Todo>> getIncompleteTodoListWithOutDailyByCategoryId(@RequestParam Long id) {
        List<Todo> resList = todoService.getIncompleteTodoListWithOutDailyByCategoryIdNotFoldersNoPage(id);
        return new ResponseResult<>(200, "查询成功", resList);
    }

    /**
     * 根据分类id层级显示所有未完成的任务（不包括每日任务）
     *
     * @param id
     * @return
     */
    @GetMapping("/list/tree")
    public ResponseResult<List<Node>> getIncompleteTodoTreeList(@RequestParam Long id) {
        List<Todo> todos = todoService.getIncompleteTodoListWithOutDailyByCategoryId(id);
        List<Node> build = TodoUtils.build(todos);
        return new ResponseResult<>(200, "查询成功", build);
    }

    /**
     * 查询所有已完成的任务（不包括每日任务）
     *
     * @return
     */
    @GetMapping("/list/completed/without/daily")
    public ResponseResult<List<TodoCompletedDto>> getCompletedTodoListWithOutDaily() {
        List<TodoCompletedDto> todos = todoService.getCompletedTodoListWithOutDaily();
        return new ResponseResult<>(200, "查询成功", todos);
    }

    /**
     * 查询今日未完成的且未取消的今日任务
     * 即：根据日期查询未完成的每日任务
     *
     * @return
     */
    @GetMapping("/list/daily/not/completed/today")
    public ResponseResult<List<Todo>> listDailyNotCompletedToday(@RequestParam Date date) {
        //先查询到所有的未取消的每日任务
        //未取消且没有添加到今天的事务（事务-任务表中没有）
        //或者：未取消但被今日的某个事务添加了，但是显示未完成状态（事务任务表中显示未完成状态）
        List<Todo> todos = todoService.listDailyNotCompletedToday(date);
        return new ResponseResult(200, "查询成功", todos);
    }

    /**
     * 根据日期查询已完成的每日任务
     *
     * @param date
     * @return
     */
    @GetMapping("/list/daily/completed/today")
    public ResponseResult<List<Todo>> listDailyCompletedToday(@RequestParam Date date) {
        List<Todo> todos = todoService.listDailyCompletedToday(date);
        return new ResponseResult(200, "查询成功", todos);
    }

    @GetMapping("/list/all/daily/completed/")
    public ResponseResult<Map<Object, Object>> listAllDailyCompleted(@RequestParam Integer page, @RequestParam Integer pageSize) {
        //查询出所有日期
        List<Date> dates = todoService.getAllDate();
        int N = dates.size();
        Map<Object, Object> resMap = new LinkedHashMap<>(N);
        resMap.put("numbers", N);
        ArrayList<CompletedThingsDaily> resList = new ArrayList<>();
        int from = (page - 1) * pageSize + 1;
        int to = from - 1 + pageSize <= N ? from - 1 + pageSize : N;
        for (int i = from - 1; i <= to - 1; i++) {
            CompletedThingsDaily completedThingsDaily = new CompletedThingsDaily(dates.get(i), todoService.listDailyCompletedToday(dates.get(i)));
            resList.add(completedThingsDaily);
        }
        resMap.put("result", resList);
        return new ResponseResult(200, "查询成功", resMap);
    }

    /**
     * 查询所有的未完成的任务id(包含今日未完成的每日任务)
     *
     * @return
     */
    @GetMapping("/list")
    public ResponseResult<List<Todo>> getTodoListIncomplete(@RequestParam Date date) {
        //要么是未完成的任务
        List<Todo> todos = todoService.getTodoListIncomplete();
        //要么是今日未完成的每日任务
        todos.addAll(todoService.getTodoListIncompleteDaily(date));
        return new ResponseResult(200, "查询成功", todos);
    }

    /**
     * 根据每日任务的任务id，取消该每日任务
     *
     * @param id
     * @return
     */
    @PutMapping("/cancel/daily")
    public ResponseResult cancelDaily(@RequestParam Long id) {
        UpdateWrapper<Todo> todoUpdateWrapper = new UpdateWrapper<>();
        todoUpdateWrapper.set("is_canceled", 1).eq("id", id);
        todoService.update(todoUpdateWrapper);
        return new ResponseResult(200, "取消成功");
    }

    /**
     * 根据任务分类id设置属于该分类的任务的默认获得
     *
     * @return
     */
    @PutMapping("/set/rule/category")
    public ResponseResult setRuleCategory(@RequestParam Long categoryId, @RequestParam Integer loveNumbers, @RequestParam Double moneyNumbers) {
        UpdateWrapper<TodoCategory> todoCategoryUpdateWrapper = new UpdateWrapper<>();
        todoCategoryUpdateWrapper.set("default_love_numbers", loveNumbers).set("default_money_numbers", moneyNumbers).eq("id", categoryId);
        todoCategoryService.update(todoCategoryUpdateWrapper);
        return new ResponseResult(200, "设置成功");
    }

    /**
     * 根据任务分类id查询该分类的默认获得
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/acquire/default/category")
    public ResponseResult<Map<String, Object>> acquireDefaultCategory(@RequestParam Long categoryId) {
        Map<String, Object> resMap = new HashMap<>(2);
        QueryWrapper<TodoCategory> todoCategoryQueryWrapper = new QueryWrapper<>();
        todoCategoryQueryWrapper.eq("id", categoryId);
        TodoCategory todoCategory = todoCategoryService.getOne(todoCategoryQueryWrapper);
        resMap.put("defaultLoveNumbers", todoCategory.getDefaultLoveNumbers());
        resMap.put("defaultMoneyNumbers", todoCategory.getDefaultMoneyNumbers());
        return new ResponseResult<>(200, "查询成功", resMap);
    }

    @PutMapping("/default/acquire")
    public ResponseResult defaultAcquire(@RequestBody DefaultCategoryAcquirementVo defaultCategoryAcquirementVo) {
        todoService.defaultAcquire(defaultCategoryAcquirementVo.getId(), defaultCategoryAcquirementVo.getDefaultMoneyNumbers(), defaultCategoryAcquirementVo.getDefaultLoveNumbers());
        return new ResponseResult(200, "修改成功");
    }


    /**
     * 根据 任务id 和 日期 判断该任务是不是真正被完成
     * 如果是每日任务 若今日任务已完成 返回今日的日期 否则返回null
     * 如果不是今日任务 若已经完成 返回完成的日期和实际消耗 否则 返回null
     *
     * @param id
     * @return
     */
    @GetMapping("/is/real/completed")
    public ResponseResult<Map<String, Date>> isRealCompleted(@RequestParam Long id, @RequestParam Date date) {
        List<TodoCompletedDto> completedTodoList = todoService.getCompletedTodoListWithOutDaily();
        for (TodoCompletedDto todoCompletedDto : completedTodoList) {
            if (todoCompletedDto.getId().equals(id)) {
                Map<String, Date> resMap = new HashMap<>(1);
                resMap.put("date", todoCompletedDto.getDate());
                return new ResponseResult<>(200, "已完成", resMap);
            }
        }
        List<Todo> todos = todoService.listDailyCompletedToday(date);
        for (Todo todo : todos) {
            if (todo.getId().equals(id)) {
                return new ResponseResult<>(200, "今日已完成");
            }
        }
        return new ResponseResult<>(200, "未完成");
    }

    /**
     * 根据时长查询获得
     *
     * @param realTime
     * @return 返回给前端
     */
    @GetMapping("/get/by/time")
    public ResponseResult<Map<String, Object>> getByTime(@RequestParam Integer realTime) {
        HashMap<String, Object> resMap = new HashMap<>(2);
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_id", 1);
        User user = userService.getOne(userQueryWrapper);
        resMap.put("loveNumbers", realTime * user.getGetLovePerMinute());
        resMap.put("moneyNumbers", realTime * user.getGetMoneyPerMinute());
        return new ResponseResult<>(200, "查询成功", resMap);
    }

    /**
     * 修改任务组分类
     *
     * @param categoryId
     * @param areaId
     * @return
     */
    @PutMapping("/change/category")
    public ResponseResult changeCategory(@RequestParam Long categoryId, @RequestParam Long areaId) {
        //查询出给定文件夹的详细信息
        QueryWrapper<Todo> todoQueryWrapper1 = new QueryWrapper<>();
        todoQueryWrapper1.eq("area_id", areaId);
        Todo tar = todoService.getOne(todoQueryWrapper1);
        //查询出所有的需要调整分类的任务
        QueryWrapper<Todo> todoQueryWrapper2 = new QueryWrapper<>();
        todoQueryWrapper2.likeRight("area_detail", tar.getAreaId());
        List<Todo> toBeChanged = todoService.list(todoQueryWrapper2);
        //进行调整
        for (Todo todo : toBeChanged) {
            todo.setTodoCategoryId(categoryId);
            todoService.updateById(todo);
        }
        return new ResponseResult(200, "修改成功");
    }

    @PutMapping("/update/daily")
    public ResponseResult updateDaily(@RequestParam Long id, @RequestParam String newName) {
        Todo todo = todoService.getById(id);
        todo.setName(newName);
        todo.setTitle(newName);
        todoService.updateById(todo);
        return new ResponseResult(200, "修改成功");
    }

}
